package game.block.input;

import game.block.Constants;
import game.block.Locator;
import game.block.command.MoveCommand;
import game.block.game.Board;
import game.block.tile.Tile;
import game.block.turn.Turn;

import java.io.IOException;

import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;

public class InputHandler implements GestureListener, InputProcessor, Constants {
    private Board gameBoard;
    private OrthographicCamera camera;
    private Vector2 touchDownPoint;

    public InputHandler(Board gameBoard, OrthographicCamera camera) {
        this.gameBoard = gameBoard;
        this.camera = camera;
    }

    @Override
    public boolean keyDown(int keycode) {
        switch (keycode) {
        case Keys.RIGHT:
            break;
        case Keys.F:
            break;
        }
        return true;
    }

    @Override
    public boolean keyUp(int keycode) {
        if (!gameBoard.isEndOfTurn()) {
            switch (keycode) {
            case Keys.U:
                if (!gameBoard.getTurns().empty()) {
                    Locator.getAudio().playSound(SOUND.UNDO.getValue());
                }
                gameBoard.undo();
                break;
            case Keys.Q:
                gameBoard.turnOver();
                break;
            case Keys.R:
                try {
                    gameBoard.restart();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case Keys.ESCAPE:
                gameBoard.returnToMenu();
            }
        }
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        switch (character) {
        case Keys.U:

            break;
        case Keys.F:
            break;
        }
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        touchDownPoint = new Vector2(screenX, screenY);
        if (!gameBoard.isEndOfTurn() && Board.DIED == false) {
            if (button == 0) {
                Vector3 pos = new Vector3(screenX, screenY, 0);
                camera.unproject(pos);
                // select a block or tile that mouse has clicked
                gameBoard.select(pos.x, pos.y);
            }
            if (button == 1) {
                gameBoard.setBlockSelected(null);
            }
        }
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        if (!gameBoard.isEndOfTurn()) {
            if (button == 0) {
                if (gameBoard.getBlockSelected() != null && gameBoard.getDraggedMove().getQueuedTiles().size() > 1) {
                    gameBoard.unhighlightAllTiles();
                    for (int i = 1; i < gameBoard.getDraggedMove().getQueuedTiles().size(); i++) {
                        // create a new turn for each queued up tile to move
                        Turn turn = new Turn();
                        turn.addCommand(new MoveCommand(gameBoard.getBlockSelected(), gameBoard.getDraggedMove().getQueuedTiles().get(i), gameBoard
                                .getDraggedMove().getQueuedTiles().get(i - 1)));

                        gameBoard.getQueuedTurns().add(turn);
                        gameBoard.getDraggedMove().getQueuedTiles().get(i).changeColor(COLOR.MOVINGTO);
                    }
                    gameBoard.getDraggedMove().getQueuedTiles().remove(0);
                    // advance turns if there are moves queued up
                    if (gameBoard.getDraggedMove().getQueuedTiles().size() > 0) {
                        gameBoard.turnOver();
                        gameBoard.getDraggedMove().getQueuedTiles().clear();
                    }
                    // rehighlight selected blocks tiles
                    else {
                        gameBoard.getBlockSelected().start(gameBoard);
                        gameBoard.getBlockSelected().highlightAdjacent();
                    }
                }
            }
        }
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        if (!gameBoard.isEndOfTurn() && gameBoard.getBlockSelected() != null ) {
            Vector3 pos = new Vector3(screenX, screenY, 0);
            camera.unproject(pos);
            // check if mouse is over original selected block, if so, clear the
            // queued move path
            checkIfSelectedTouched(pos);
            // search for tiles that mouse is hovering over, if they are valid
            // move spaces, add to the path
            for (Tile tile : gameBoard.getDraggedMove().getAdjacentTiles()) {
                if (tile.getPosition().x <= pos.x && tile.getPosition().x + TILE_SIZE >= pos.x && tile.getPosition().y <= pos.y
                        && tile.getPosition().y + TILE_SIZE >= pos.y) {
                    // remove last tile from the path
                    if (gameBoard.getDraggedMove().getQueuedTiles().size() > 1
                            && (gameBoard.getDraggedMove().getQueuedTiles().get(gameBoard.getDraggedMove().getQueuedTiles().size() - 2).equals(tile) || false)) {
                        gameBoard.getDraggedMove().getQueuedTiles().remove(
                                gameBoard.getDraggedMove().getQueuedTiles().get(gameBoard.getDraggedMove().getQueuedTiles().size() - 1));
                        gameBoard.getDraggedMove().getCurrentTile().changeColor(COLOR.BLANK);
                        gameBoard.getDraggedMove().setCurrentTile(tile);
                        gameBoard.getDraggedMove().updateAdjacentTiles();
                        break;
                    }
                    // add new tile to the path
                    else {
                        if (!gameBoard.getDraggedMove().getQueuedTiles().contains(tile)) {
                            // gameBoard.getBlockSelected().unhighlightAdjacent();
                            Locator.getAudio().playSound(SOUND.HOVER.getValue());
                            gameBoard.getDraggedMove().getQueuedTiles().add(tile);
                            tile.changeColor(COLOR.MOVINGTO);
                            gameBoard.getDraggedMove().setCurrentTile(tile);
                            gameBoard.getDraggedMove().updateAdjacentTiles();
                            break;
                        }
                    }
                }
            }
        } else {
            float deltaX=touchDownPoint.x - screenX;
            float deltaY=touchDownPoint.y - screenY;
            gameBoard.getScreen().moveCamera(deltaX*0.2f,-deltaY*0.2f);
        }
        touchDownPoint.x = screenX;
        touchDownPoint.y = screenY;
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {

        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        if (amount == 1) {
            if (camera.zoom < 1.5f) {
                camera.zoom += 0.1f;
            }
        } else {
            if (camera.zoom > 0.5f) {
                camera.zoom -= 0.1f;
            }
        }
        return false;
    }

    public void checkIfSelectedTouched(Vector3 pos) {
        if (gameBoard.getBlockSelected().getCurrentTile().getPosition().x <= pos.x
                && gameBoard.getBlockSelected().getCurrentTile().getPosition().x + TILE_SIZE >= pos.x
                && gameBoard.getBlockSelected().getCurrentTile().getPosition().y <= pos.y
                && gameBoard.getBlockSelected().getCurrentTile().getPosition().y + TILE_SIZE >= pos.y) {
            gameBoard.getDraggedMove().getQueuedTiles().clear();
            gameBoard.getDraggedMove().startDrag(gameBoard.getBlockSelected().getCurrentTile());
            gameBoard.getBlockSelected().start(gameBoard);
            gameBoard.getBlockSelected().highlightAdjacent();
        }
    }

    @Override
    public boolean touchDown(float x, float y, int pointer, int button) {
        System.out.println("touch");
        return false;
    }

    @Override
    public boolean tap(float x, float y, int count, int button) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean longPress(float x, float y) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean fling(float velocityX, float velocityY, int button) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean pan(float x, float y, float deltaX, float deltaY) {
        System.out.println("panning");
        if (!gameBoard.isEndOfTurn() && gameBoard.getBlockSelected() != null) {

        } else {
            camera.translate(deltaX, deltaY);
        }
        return false;
    }

    @Override
    public boolean panStop(float x, float y, int pointer, int button) {
        System.out.println("pan Stop");
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean zoom(float initialDistance, float distance) {
        System.out.println("zoom");
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
        System.out.println("pinch");
        // TODO Auto-generated method stub
        return false;
    }

}
